package com.feidu.utils;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

/**
 * 
 * 描述：下载任务 AsyncTask对线程和handler进行了封装
 * 
 * Params 开始异步任务执行时传入的参数类型，即doInBackground()方法中的参数类型 Progress
 * 异步任务执行过程中，返回下载进度值的类型，即在doInBackground中调用publishProgress()时传入的参数类型 Result
 * 异步任务执行完成后，返回的结果类型，即doInBackground()方法的返回值类型
 * 
 * AsyncTask内部使用的是线程池，相当于里面有一个线程队列，执行一次execute时会将一个下载任务加入到线程队列，只有前一个任务完成了，下一个下载任务才会开始执行
 * 
 * 使用小结：
（1）AsyncTask中，只有doInBackground()方法是处于子线程中运行的，其他三个回调onPreExecute()、onPostExecute()、onProgressUpdate()都是在UI线程中进行，因此在这三个方法里面可以进行UI的更新工作；
（2）每一个new出的AsyncTask只能执行一次execute()方法，多次运行将会报错，如需多次，需要新new一个AsyncTask；
（3）AsyncTask必须在UI线程中创建实例，execute()方法也必须在UI线程中调用；
 */
public class DownloadAsyncTask extends AsyncTask<String, Integer, Bitmap> {

	private ProgressBar mPreogressBar;// 进度条
	private ImageView mImageView;// 图片显示控件

	public DownloadAsyncTask(ProgressBar progressBar, ImageView imageView) {

		this.mPreogressBar = progressBar;
		this.mImageView = imageView;

	}

	// 任务开始前
	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		this.mPreogressBar.setVisibility(View.VISIBLE);
	}

	/**
	 * 执行后台下载操作的方法，必须实现的一个方法，运行在子线程中
	 */
	@Override
	protected Bitmap doInBackground(String... params) {
		// 拿execute()传过来的图片url
		String urlParams = params[0];
		Bitmap bitmap = null;
		URLConnection conn = null;
		InputStream is = null;

		try {
			URL url = new URL(urlParams);
			conn = url.openConnection();
			is = conn.getInputStream();

			// 这里只是为了演示更新进度的功能，实际的进度值需要在从输入流中读取时逐步获取
			for (int i = 0; i < 100; i++) {
				//通过isCancelled()判断任务任务是否被取消
				if (isCancelled()) {
					
					break;
				}
				// 向用户展示文件的下载进度情况
				// publishProgress()内部会去调用AsyncTask的另一个回调方法onProgressUpdate()运行在主线程中
				publishProgress(i);
				Thread.sleep(50);// 为了看清效果，睡眠一段时间
			}
			// 将获取到的输入流转成Bitmap
			BufferedInputStream bis = new BufferedInputStream(is);
			bitmap = BitmapFactory.decodeStream(bis);

			is.close();
			bis.close();
		} catch (IOException e) {

			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		return bitmap;
	}

	// 进度提示
	@Override
	protected void onProgressUpdate(Integer... values) {
		super.onProgressUpdate(values);
		//通过isCancelled()判断任务任务是否被取消
		if (isCancelled()) {
			
			return;
		}
		mPreogressBar.setProgress(values[0]);
	}

	// 任务完成
	@Override
	protected void onPostExecute(Bitmap result) {
		super.onPostExecute(result);

		this.mPreogressBar.setVisibility(View.GONE);
		mImageView.setImageBitmap(result);
	}

	/**
	 * 实际项目中如何获取文件大小作为进度值及更新进度值
	 * 
	 * @param conn
	 * @param is
	 */
	private void progressSize(URLConnection conn, InputStream is) {
		try {
			// 实际项目中如何获取文件大小作为进度值及更新进度值
			int totalSize = conn.getContentLength();// 获取文件总大小
			int size = 0;// 保存当前下载文件的大小，作为进度值
			int count = 0;
			byte[] buffer = new byte[1024];
			while ((count = is.read(buffer)) != -1) {
				size += count;// 获取已下载的文件大小
				// 调用publishProgress更新进度，它内部会回调onProgressUpdate()方法
				publishProgress(size, totalSize);
				Thread.sleep(100);// 为了看清效果，睡眠一段时间
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
